#pragma once

#include "AST.h"
#include "SymbolTable.h"
#include <vector>
#include <memory>
#include <string>

namespace MiniDB {

// 执行计划算子基类
class PlanOperator {
public:
    virtual ~PlanOperator() = default;
    virtual std::string getType() const = 0;
    virtual std::string toString(int indent = 0) const = 0;
    virtual std::shared_ptr<PlanOperator> getChild() const { return nullptr; }
};

// 顺序扫描算子
class SeqScanOperator : public PlanOperator {
public:
    explicit SeqScanOperator(const std::string& table_name);
    std::string getType() const override { return "SeqScan"; }
    std::string toString(int indent = 0) const override;
    const std::string& getTableName() const { return table_name_; }

private:
    std::string table_name_;
};

// 过滤算子
class FilterOperator : public PlanOperator {
public:
    FilterOperator(std::shared_ptr<PlanOperator> child, std::shared_ptr<Expression> condition);
    std::string getType() const override { return "Filter"; }
    std::string toString(int indent = 0) const override;
    std::shared_ptr<PlanOperator> getChild() const override { return child_; }
    std::shared_ptr<Expression> getCondition() const { return condition_; }

private:
    std::shared_ptr<PlanOperator> child_;
    std::shared_ptr<Expression> condition_;
};

// 投影算子
class ProjectOperator : public PlanOperator {
public:
    ProjectOperator(std::shared_ptr<PlanOperator> child, const std::vector<std::shared_ptr<Expression>>& projections);
    std::string getType() const override { return "Project"; }
    std::string toString(int indent = 0) const override;
    std::shared_ptr<PlanOperator> getChild() const override { return child_; }
    const std::vector<std::shared_ptr<Expression>>& getProjections() const { return projections_; }

private:
    std::shared_ptr<PlanOperator> child_;
    std::vector<std::shared_ptr<Expression>> projections_;
};

// 插入算子
class InsertOperator : public PlanOperator {
public:
    InsertOperator(const std::string& table_name, const std::vector<std::vector<std::shared_ptr<Expression>>>& values);
    std::string getType() const override { return "Insert"; }
    std::string toString(int indent = 0) const override;
    const std::string& getTableName() const { return table_name_; }
    const std::vector<std::vector<std::shared_ptr<Expression>>>& getValues() const { return values_; }

private:
    std::string table_name_;
    std::vector<std::vector<std::shared_ptr<Expression>>> values_;
};

// 更新算子
class UpdateOperator : public PlanOperator {
public:
    UpdateOperator(const std::string& table_name,
                  const std::vector<std::pair<std::string, std::shared_ptr<Expression>>>& assignments,
                  std::shared_ptr<Expression> condition = nullptr);
    std::string getType() const override { return "Update"; }
    std::string toString(int indent = 0) const override;
    const std::string& getTableName() const { return table_name_; }
    const std::vector<std::pair<std::string, std::shared_ptr<Expression>>>& getAssignments() const { return assignments_; }
    std::shared_ptr<Expression> getCondition() const { return condition_; }

private:
    std::string table_name_;
    std::vector<std::pair<std::string, std::shared_ptr<Expression>>> assignments_;
    std::shared_ptr<Expression> condition_;
};

// 删除算子
class DeleteOperator : public PlanOperator {
public:
    DeleteOperator(const std::string& table_name, std::shared_ptr<Expression> condition = nullptr);
    std::string getType() const override { return "Delete"; }
    std::string toString(int indent = 0) const override;
    const std::string& getTableName() const { return table_name_; }
    std::shared_ptr<Expression> getCondition() const { return condition_; }

private:
    std::string table_name_;
    std::shared_ptr<Expression> condition_;
};

// 创建表算子
class CreateTableOperator : public PlanOperator {
public:
    CreateTableOperator(const std::string& table_name, const std::vector<std::shared_ptr<ASTNode>>& columns);
    std::string getType() const override { return "CreateTable"; }
    std::string toString(int indent = 0) const override;
    const std::string& getTableName() const { return table_name_; }
    const std::vector<std::shared_ptr<ASTNode>>& getColumns() const { return columns_; }

private:
    std::string table_name_;
    std::vector<std::shared_ptr<ASTNode>> columns_;
};

// 执行计划
class ExecutionPlan {
public:
    ExecutionPlan() = default;

    void setRoot(std::shared_ptr<PlanOperator> root) { root_ = root; }
    std::shared_ptr<PlanOperator> getRoot() const { return root_; }

    std::string toString() const;
    void print() const;

private:
    std::shared_ptr<PlanOperator> root_;
};

// 执行计划生成器
class PlanGenerator {
public:
    explicit PlanGenerator(SymbolTable& symbol_table);
    std::unique_ptr<ExecutionPlan> generatePlan(const std::vector<std::shared_ptr<Statement>>& statements);

    // 启用/禁用谓词下推优化
    void enablePredicatePushdown(bool enable) { predicate_pushdown_enabled_ = enable; }
    bool isPredicatePushdownEnabled() const { return predicate_pushdown_enabled_; }

private:
    SymbolTable& symbol_table_;
    bool predicate_pushdown_enabled_ = true; // 默认启用

    std::shared_ptr<PlanOperator> generateStatementPlan(std::shared_ptr<Statement> stmt);
    std::shared_ptr<PlanOperator> generateSelectPlan(std::shared_ptr<SelectStatement> stmt);
    std::shared_ptr<PlanOperator> generateInsertPlan(std::shared_ptr<InsertStatement> stmt);
    std::shared_ptr<PlanOperator> generateUpdatePlan(std::shared_ptr<UpdateStatement> stmt);
    std::shared_ptr<PlanOperator> generateDeletePlan(std::shared_ptr<DeleteStatement> stmt);
    std::shared_ptr<PlanOperator> generateCreateTablePlan(std::shared_ptr<CreateTableStatement> stmt);
};

// 公开的查询执行接口
std::vector<std::unordered_map<std::string, std::variant<std::string, int, double>>>
executeSelectQuery(std::shared_ptr<SelectStatement> select_stmt);

} // namespace MiniDB
